package executables;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;

import data_structs.HashRB;
import data_structs.SequenceWrapper;
import errors.DuplicateKey;
import errors.IncorrectNucleotide;

public class AppTester {

	public static void main(String[] args) throws IOException, IncorrectNucleotide {
		System.out.println("Max memory: "+Runtime.getRuntime().maxMemory());
		System.out.println(Runtime.getRuntime().totalMemory());
		long start = System.currentTimeMillis();
		
		//Windows file location
		String f_51hits = "C:/Users/DC/Documents/Work/Miscellaneous/51.hits.fa";
		String f1 = "C:/Users/DC/Documents/Work/workspace/SequenceMatching/src/files/testfile1.txt";
		String f2 = "C:/Users/DC/Documents/Work/workspace/SequenceMatching/src/files/testfile2.txt";
		String f3 = "C:/Users/DC/Documents/Work/workspace/SequenceMatching/src/files/testfile3.txt";
		String microbe377Small = "C:/Users/DC/Documents/Work/workspace/SequenceMatching/src/files/m377-small.txt";
		String microbe114Small = "C:/Users/DC/Documents/Work/workspace/SequenceMatching/src/files/m114-small.txt";
		String microbe377Full = "C:/Users/DC/Documents/Work/Metagenomes/microbe377/55.fna";
		String microbe114Full = "C:/Users/DC/Documents/Work/Metagenomes/microbe114/57.fna";
		
		String hashFile = f_51hits;
		String queryFile = f1;
		
		//Mac file locations
//		String hashFile = "/Users/DG/Documents/Daniel Work/Miscellaneous/51.hits.fa";
//		String f1 = "/Users/DG/Documents/Daniel Work/workspace/SequenceMatching/src/files/testfile1.txt";
//		String f2 = "/Users/DG/Documents/Daniel Work/workspace/SequenceMatching/src/files/testfile2.txt";
//		String f3 = "/Users/DG/Documents/Daniel Work/workspace/SequenceMatching/src/files/testfile3.txt";
		
		//octopussy file locations
//		String microbe377Small = "/home/dcuevas/sequencematching/src/files/m377-small.txt";
//		String microbe114Small = "/home/dcuevas/sequencematching/src/files/m114-small.txt";
		
		//rohan file locations
//		String microbe377Small = "/home/ma/u/dcuevas/SequenceMatching/src/files/m377-small.txt";
//		String microbe114Small = "/home/ma/u/dcuevas/SequenceMatching/src/files/m114-small.txt";
//		String microbe377Full = "/home/ma/u/dcuevas/SequenceMatching/src/files/microbe377";
//		String microbe114Full = "/home/ma/u/dcuevas/SequenceMatching/src/files/microbe114";
		
		File readFile = new File(hashFile);
		int kmer = 15;
//		HashRB<SequenceWrapper> ht = new HashRB<SequenceWrapper>(1000003);
		HashRB<SequenceWrapper> ht = new HashRB<SequenceWrapper>();

		BufferedReader reader = new BufferedReader(new FileReader(readFile));
		String txt = null;
		
		long startHash, startSearch;
		double hTime, sTime;
		startHash = System.currentTimeMillis();
		while( reader.ready() ) {
			txt = reader.readLine();
			String id = txt.substring(1);
			String sequence = reader.readLine();
			int idx = 0;
			int endLoop = sequence.length()-kmer; //Stopping condition
			while( idx <= endLoop ) {
				String seqToAdd = sequence.substring(idx, idx+kmer);
				//Get compliment
				String compSeq = reversal(getCompliment(seqToAdd));
				SequenceWrapper sw = null;
				SequenceWrapper swComp = null;
				try {
					sw = new SequenceWrapper(id,seqToAdd,idx, false);
					swComp = new SequenceWrapper(id,compSeq,idx, true);
				} catch (Exception e2) {
					System.err.println(seqToAdd);
					e2.printStackTrace();
					return;
				}
				try {
					//Loop to keep trying to add sw when hash returns false
					while( !ht.add(sw) )
						sw.increaseTreeFixer();
					idx++;
					//Loop to keep trying to add swComp when hash returns false
					while( !ht.add(swComp) )
						swComp.increaseTreeFixer();
				} catch (DuplicateKey e1) {
					e1.printStackTrace();
				} catch(ArrayIndexOutOfBoundsException e) {
					e.printStackTrace();
					System.out.println(sw);
					return;
				}
			}
		}
		reader.close();
		
		hTime =(double) (System.currentTimeMillis()-startHash)/1000;
		
//		startSearch = System.currentTimeMillis();
//		
//		/** *********Test to search for a specific sequence**************
//		
//		SequenceWrapper find = new SequenceWrapper("15543", "CAACGGCAACGACAA", 53);
//		String[] results = (ht.contains(find)).split("\\$");
//		for( String obj : results )
//			System.out.println(obj);
//		System.out.println("Number found: "+results.length);
//		sTime = (double) (System.currentTimeMillis()-startSearch)/1000;
//		
//		double totalTime = (double) (System.currentTimeMillis()-start)/1000;
//		
//		
		String[] status = (ht.hashStatus()).split("\\$");
		for( String toPrint : status )
			System.out.print(toPrint);
		System.out.println("Hash Time: "+hTime);
		System.out.println("Number of objects = "+ht.numObjects());
//				
//		System.out.println("***Time Results***\n" +
//				"Hash time: "+hTime+"\n" +
//				"Search time: "+sTime+"\n" +
//				"Total time: "+totalTime);
//		*/
//		
//		Calendar cal = Calendar.getInstance();
//		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd @ HH.mm.ss");
//		String resultsFileName = sdf.format(cal.getTime());
//		
//		PrintWriter pw = new PrintWriter(new FileWriter("results/"+resultsFileName+".txt"));
//		readFile = new File(queryFile);
//		reader = new BufferedReader(new FileReader(readFile));
//		pw.println("Hashed File: "+hashFile);
//		pw.println("Query File: "+queryFile);
//		pw.println();
////		ArrayList<String> searched = new ArrayList<String>();
//		
//		startSearch = System.currentTimeMillis();
//		
//		txt = null;
//		//Start reading file
//		while( (txt=reader.readLine()) != null ) {
//			//Get current id
//			String id = txt.substring(1);
//			//Get current sequence
//			String sequence = reader.readLine();
//			int idx = 0;
//			int endLoop = sequence.length()-kmer; //Stopping condition
//			while( idx <= endLoop ) {
//				String seqToFind = sequence.substring(idx, idx+kmer);
//				pw.println("Attempt to find: "+seqToFind+", ID: "+id+", Position: "+idx);
////				if( !searched.contains(seqToFind) ) {
////					searched.add(seqToFind);
////					System.out.println("Starting to find sequence "+seqToFind);
//					//Create SequenceWrapper with current kmer-length sequence
//					SequenceWrapper sw = new SequenceWrapper(id,seqToFind,idx);
//					//Find where current sequence appears in first file
////					String[] results = ht.contains(sw).split("\\$");
//					ArrayList<String> results = ht.contains(sw);
//					//Print out results into result file
//					pw.println("*****Results*****");
//					if( results == null )
//						pw.println("Sequence not found.");
//					else {
//						for( String obj : results ) 
//							pw.println(obj);
//						int numFound = results.size();
//						pw.println((numFound == 1) ? "Found "+numFound+" match." : "Found "+numFound+" matches.");
//					}
////				}
////				else
////					pw.println("Sequence was already searched for.");
//				pw.println();
//				pw.println("***********************************************");
//				pw.println();
//				idx++;
//			}
//			System.out.println("Finished sequence id "+id);
//		}
//		sTime = (double) (System.currentTimeMillis()-startSearch)/1000;
//		double totalTime = (double) hTime+sTime;
//		
//		pw.println("***Time Results***");
//		pw.println("Hash time: "+hTime);
//		pw.println("Search time: "+sTime);
//		pw.println("Total time: "+totalTime);
//		pw.close();
//		reader.close();
//		
//		System.out.println("***Time Results***");
//		System.out.println("Hash time: "+hTime);
//		System.out.println("Search time: "+sTime);
//		System.out.println("Total time: "+totalTime);
		System.out.println("Memory left over: "+java.lang.Runtime.getRuntime().freeMemory());
	}
	
	public static String reversal(String seq) {
		return seq = new StringBuffer(seq).reverse().toString();
	}
	
	public static String getCompliment(String seq) throws IncorrectNucleotide {
		String ret = "";
		for( int i = 0; i < seq.length(); i++ ) {
			char curr = seq.charAt(i);
			switch(curr) {
				case 'A': ret += "T"; break;
				case 'T': ret += "A"; break;
				case 'C': ret += "G"; break;
				case 'G': ret += "C"; break;
				case 'N': ret += "N"; break;
				default: throw new IncorrectNucleotide("Nucleotide '" + curr + "' is not valid.");
			}
		}
		return ret;
	}
	
}
